cbuffer cbPerObject
{
    float4x4 sys_TransformMatrix;
};

cbuffer cbTerrain
{
    float terra_scale;
    float tile_tex_size;
};

struct VS_IN
{
    float3 Vertex : POSITION;
};

struct VS_OUT
{
    float2 TexCoord : TEXCOORD;
    float2 NMapCoord : NMAPCOORD;
    float4 Pos : SV_POSITION;
};

struct PS_OUT
{
    float4 Albedo : SV_TARGET0;
    float4 Normal : SV_TARGET1;
};

SamplerState gTerrainTileSamp
{
    Filter = ANISOTROPIC;
    AddressU = WRAP;
    AddressV = WRAP;
    MaxAnisotropy = 4;
};

SamplerState gTerrainTexSamp
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = CLAMP;
    AddressV = CLAMP;
};

Texture2D alphamap;
Texture2D normalmap;
Texture2D textures[3];

VS_OUT VS(VS_IN vIn)
{
    VS_OUT vOut;
    vOut.TexCoord = vIn.Vertex.xz * tile_tex_size;
    vOut.NMapCoord = vIn.Vertex.xz / terra_scale + 0.5f;
    vOut.Pos = mul(float4(vIn.Vertex, 1.0f), sys_TransformMatrix);
    return vOut;
}

PS_OUT PS(VS_OUT pIn)
{
    PS_OUT pOut;
    float3 normal = normalize(normalmap.Sample(gTerrainTexSamp, pIn.NMapCoord).xyz);
    pOut.Albedo = float4(0.0, 0.0, 0.0, 0.0);
    pOut.Normal = float4(normal.xyz*0.5 + 0.5, 0.0);
    float3 amapcolor = alphamap.Sample(gTerrainTexSamp, pIn.NMapCoord).xyz;
    if(amapcolor.x != 0.0f)
        pOut.Albedo.xyz += amapcolor.x * textures[0].Sample(gTerrainTileSamp, pIn.TexCoord).xyz;
    if(amapcolor.y != 0.0f)
        pOut.Albedo.xyz += amapcolor.y * textures[1].Sample(gTerrainTileSamp, pIn.TexCoord).xyz;
    if(amapcolor.z != 0.0f)
        pOut.Albedo.xyz += amapcolor.z * textures[2].Sample(gTerrainTileSamp, pIn.TexCoord).xyz;
    return pOut;
}

technique10 TerrainRenderer
{
    pass P0
    {
        SetVertexShader(CompileShader(vs_4_0, VS()));
        SetGeometryShader(NULL);
        SetPixelShader(CompileShader(ps_4_0, PS()));
    }
}
